package ferp.core.ai.strategy.simple;

import ferp.core.ai.strategy.Tricking;
import ferp.core.card.Card;
import ferp.core.game.Game;
import ferp.core.player.AI;
import ferp.core.player.Hand;

/**
 * User: igorgok
 * Date: 5/30/11 5:18 PM
 */
public class SimpleTricking extends Tricking
{
/*
  private Card firstHandDeclarerMove(AI ai)
  {
    Hand candidates = Game.ferp().current.player.hand.getMoveCandidates();
    Card.Suit trump = Game.ferp().trump();

    // playing without trump - put the highest card among all suits
    if (trump == Card.Suit.NONE)
      return candidates.highest(Game.ferp().deck());

    Card.Set myTrumpCards = new Card.Set(candidates.cards(trump));

    // trump still in the game
    Card.Set restTrumpCards = new Card.Set(myTrumpCards, Game.ferp().trash.cards(trump));
    restTrumpCards.invert();

    // if there are still trump cards in game - try to win them first
    if (restTrumpCards.size() > 0)
    {
      Card.Rank maxTrump = restTrumpCards.highest();
      Card.Rank greater = myTrumpCards.higher(maxTrump);

      // have no greater trump card than max trump card that still in game - put the highest one
      if (greater == null)
        return candidates.highest(Game.ferp().deck());

      // win trump cards
      return Game.ferp().deck().card(trump, greater);
    }

    return candidates.highest(Game.ferp().deck());
  }

  private Card secondHandDeclarerMove(AI ai)
  {
    Hand candidates = Game.ferp().current.player.hand.getMoveCandidates();

    // playing without trump - put the highest card among all suits
    if (Game.ferp().trump() == null)
      return candidates.highest(Game.ferp().deck());

    // first player move
    Card first = Game.ferp().trick.first();

    // find highest card of the first player card's suit
    Card.Rank highest = candidates.cards(first.suit()).highest();

    // no cards of this suit
    if (highest == null)
      return candidates.lowest(Game.ferp().deck());

    // try to win this trick
    return Game.ferp().deck().card(first.suit(), highest);
  }

  private Card thirdHandDeclarerMove(AI ai)
  {
    Hand candidates = Game.ferp().current.player.hand.getMoveCandidates();

    Card highest = Game.ferp().trick.highest(Game.ferp().trump());

    // try to win a trick with the card that greater than the highest one in the trick
    Card.Rank greater = candidates.cards(highest.suit()).higher(highest.rank());

    // no greater card found - put minimal card
    if (greater == null)
      return candidates.lowest(Game.ferp().deck());

    // win the trick by putting greater card
    return Game.ferp().deck().card(highest.suit(), greater);
  }

  // get weakest card ("semak")
  private Card weakest(Hand candidates)
  {
      Card.Suit suit = null;
      int min = 9;

      for (Card.Suit s : Card.Suit.rising)
      {
        Card.Set set = candidates.cards(s);

        if (set.size() > 0)
        {
          // has no whists in this suit - can move a card from this suit only if its not trump
          // (let declarer play trump cards)
          boolean trump = (s == Game.ferp().trump());

          if (!trump && Estimate.whists(set, trump) == 0 && set.size() < min)
          {
            suit = s;
            min = set.size();
          }
        }
      }

      // has whists in all suits - just return the lowest card
      if (suit == null)
      {
        return candidates.lowest(Game.ferp().deck());
      }

      // return the lowest card in the shortest "safe" suit
      return candidates.lowest(Game.ferp().deck(), suit);
  }

  // get strongest card ("tuzuyushii")
  private Card strongest(Hand candidates)
  {
    Card.Suit suit = null;
    int max = 0;

    for (Card.Suit s : Card.Suit.rising)
    {
      Card.Set set = candidates.cards(s);

      // has no whists in this suit - can move a card from this suit only if its not trump
      // (let declarer play trump cards)
      boolean trump = (s == Game.ferp().trump());

      if (!trump && Estimate.whists(set, trump) == 0 && set.size() > max)
      {
        suit = s;
        max = set.size();
      }
    }

    // has whists in all suits - just return the highest card
    if (suit == null)
    {
      return candidates.highest(Game.ferp().deck());
    }

    // return the highest card in the longest "safe" suit
    return candidates.highest(Game.ferp().deck(), suit);
  }

  private Card firstHandWhisterMove(AI ai)
  {
    Hand candidates = Game.ferp().current.player.hand.getMoveCandidates();

    boolean beforeDeclarer = (Game.ferp().next(Game.ferp().current.player) == Game.ferp().declarer);

    // next player is declarer - find weakest card to move ("semak")
    if (beforeDeclarer)
      return weakest(candidates);

    // next player is whisting\passing - find strongest card to move ("tuzuyushii")
    return strongest(candidates);
  }

  private Card secondHandWhisterMove(AI ai)
  {
    Hand candidates = Game.ferp().current.player.hand.getMoveCandidates();

    boolean beforeDeclarer = (Game.ferp().next(Game.ferp().current.player) == Game.ferp().declarer);

    // next player is declarer, i.e. first whister/passer made his move
    if (beforeDeclarer)
    {
        // if has cards of the first player move's suit - put minimal (assumes that first player put the strongest one)
        // this situation is equivalent for both cases: with\without trump
        if (candidates.cards(Game.ferp().trick.first().suit()).size() > 0)
          return candidates.lowest(Game.ferp().deck(), Game.ferp().trick.first().suit());

        // otherwise return lowest card in first found non-empty suit
        return candidates.lowest(Game.ferp().deck());
    }

    // declarer made a move - if such suit exists then try to win the trick with greater card
    Card first = Game.ferp().trick.first();
    Card.Set set = candidates.cards(first.suit());
    if ((set.size() > 0) && (set.higher(first.rank()) != null))
      return Game.ferp().deck().card(first.suit(),set.higher(first.rank())) ;

    // otherwise return lowest card in first found non-empty suit
    return candidates.lowest(Game.ferp().deck());
  }

  private Card thirdHandWhisterMove(AI ai)
  {
    Hand candidates = Game.ferp().current.player.hand.getMoveCandidates();

    Card highest = Game.ferp().trick.highest(Game.ferp().trump());

    // the highest card in the trick belongs to the declarer - try to win the trick
    if (Game.ferp().trick.get(Game.ferp().declarer) == highest)
    {
        Card.Rank greater = candidates.cards(highest.suit()).higher(highest.rank());

        // no greater card found - put minimal card
        if (greater == null)
          return candidates.lowest(Game.ferp().deck());

        // win the trick by putting greater card
        return Game.ferp().deck().card(highest.suit(), greater);
    }

    // the highest card in the trick belongs to other whister\passer - try to let him win the trick
    return candidates.lowest(Game.ferp().deck());
  }
*/

  @Override
  public Game.Type type(Game g)
  {
    if (g.contract() < 8 && g.bid.trump != Card.Suit.NONE &&
        Hand.only(g.getOpponentHand().current, g.bid.trump) != 0 &&
        g.player.starting != g.player.opponent)
    {
      if (Hand.suits(g.getOpponentHand().current) < 4)
        return Game.Type.STANDING;

      // look up non-trump suit with exactly 1 card
      for (Card.Suit s : Card.Suit.rising)
        if (s != g.bid.trump && Card.Set.size(Card.Set.get(g.getOpponentHand().current, s)) == 1)
          return Game.Type.STANDING;
    }

    return Game.Type.OPEN;
  }

  @Override
  public Card move(AI ai)
  {
/*
    switch (Game.ferp().hand)
    {
      // first hand
      case 0: return (ai == Game.ferp().declarer) ? firstHandDeclarerMove(ai)  : firstHandWhisterMove(ai);

      // second hand
      case 1: return (ai == Game.ferp().declarer) ? secondHandDeclarerMove(ai) : secondHandWhisterMove(ai);

      // third hand
      case 2: return (ai == Game.ferp().declarer) ? thirdHandDeclarerMove(ai)  : thirdHandWhisterMove(ai);
    }

    // should never get here
    assert false;
*/

    return null;
  }
}
